package com.huishi.util;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 命令行工具类
 */
@Slf4j
public class CMDUtils {
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH_mm_ss");


    //一般的执行方法，有时执行exe会卡在那    stmt要执行的命令
    public static Map<String, Object> executive(String stmt) {
        Map<String, Object> result = new HashMap<>(2);

        Runtime runtime = Runtime.getRuntime();  //获取Runtime实例
        //执行命令
        try {
            String[] command = {"cmd", "/c", stmt};
            Process process = runtime.exec(command);

            // 标准输入流（必须写在 waitFor 之前）
            String inStr = consumeInputStream(process.getInputStream());
            // 标准错误流（必须写在 waitFor 之前）
            String errStr = consumeInputStream(process.getErrorStream()); //若有错误信息则输出

            int proc = process.waitFor();
            if (proc == 0) {
                System.out.println("执行成功" + inStr);
                result.put("result", true);
                result.put("value", inStr);
            } else {
                System.out.println("执行失败" + errStr);
                result.put("result", false);
                result.put("value", errStr);
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            result.put("result", false);
            result.put("value", e.getMessage());
        }

        return result;
    }


    /**
     * 消费inputstream，并返回
     */
    public static String consumeInputStream(InputStream is) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(is, "GBK"));
        String s;
        StringBuilder sb = new StringBuilder();
        while ((s = br.readLine()) != null) {
            System.out.println(s);
            sb.append(s);
        }
        return sb.toString();
    }

    public static boolean executiveDataX(String stmt, String jobName, Date startTime) {

        Runtime runtime = Runtime.getRuntime();
        try {
            String[] command = {"cmd", "/c", stmt};
            Process process = runtime.exec(command);

            // 处理日志目录
            String logFolder = "./logs/datax/" + DATE_FORMAT.format(startTime) + "/";
            FileUtils.createFolder(logFolder);
            String logFileName = logFolder + jobName + "-" + TIME_FORMAT.format(startTime) + ".log";
            // 启动两个线程分别处理输入和错误流
            StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT", logFileName);
            StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR", null);
            new Thread(outputGobbler).start();
            new Thread(errorGobbler).start();

            // 阻塞主线程，等待子进程完成
            int proc = process.waitFor();
            return proc == 0;
        } catch (IOException | InterruptedException e) {
            log.error("DataX任务执行失败：", e);
            return false;
        }

    }

    // StreamGobbler 类，用于处理流
    private static class StreamGobbler implements Runnable {
        private final InputStream inputStream;
        private final String streamType;
        private StringBuilder output = new StringBuilder();
        private String logFileName;

        StreamGobbler(InputStream inputStream, String streamType, String logFileName) {
            this.inputStream = inputStream;
            this.streamType = streamType;
            this.logFileName = logFileName;
        }

        public void run() {
            FileWriter writer = null;
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
                if(logFileName != null)
                    writer = new FileWriter(logFileName, true);

                String line;
                while ((line = reader.readLine()) != null) {
                    if(writer != null) writer.write(line + "\n");
                    output.append(line).append("\n");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(writer != null) {
                    try {
                        writer.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
//            log.info("result::::{}", output.toString());
        }

        public String getOutput() {
            return output.toString();
        }
    }
}
